
/**
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * GenericProvider is a data driven content provider for Android.
 * @author Tim Kelsey <tim.callidus@gmail.com>
 */

package callidus.bits.GenericProvider;

import java.util.List;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;

import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;

import android.text.TextUtils;
import android.util.Log;

// NOTE: ok here we make a big assumption, though its ok in most cases.
// if we have more than one part in our URL path than we assume the url
// to hold be COLUMN/_ID this avoids using Uri matching. Also we assume
// that the _ID column is called "_id" ...

public class GenericProvider extends ContentProvider {

	private GenericDatabase mDbHelper = null;

	@Override
	public String getType(Uri uri){
		// make sure its parsed the DB schemer
		mDbHelper.getReadableDatabase();
		List<String> bits = uri.getPathSegments();
		
		String ret = null;
		switch( bits.size() ){
		case 1:
			ret = "vnd.android.cursor.dir/" + mDbHelper.getMime( bits.get( 0 ) );
			break;
						
		case 2:
			ret = "vnd.android.cursor.item/" + mDbHelper.getMime( bits.get( 0 ) );
			break;
			
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
		
		return ret;
	}

	
	@Override
	public boolean onCreate() {
		Log.println(Log.INFO, "GenericProvider", "GenericProvider is Online\n" );
		Context ctx = getContext();
		mDbHelper = new GenericDatabase( ctx, ctx.getResources().getString( R.string.db_name ), 
				null, Integer.parseInt( ctx.getResources().getString( R.string.db_version ) ), 
				R.xml.database_schema );
		
		return true; // should do some error handling ?
	}

	
	@Override
	public Cursor query( Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder ) {
		Log.println(Log.INFO, "GenericProvider", "Running Query\n" );
		
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		List<String> bits = uri.getPathSegments(); 
		if( bits.size() == 2 ){
			qb.appendWhere( "_id = " + bits.get( 1 ) );
		}
		qb.setTables( bits.get( 0 ) );
		String qry = qb.buildQuery( projection, selection, selectionArgs, null, null, sortOrder, null );
		
		Log.println( Log.INFO, "GenericProvider", "qry " + qry + "\n" );
		
		SQLiteDatabase db = mDbHelper.getReadableDatabase();
		Cursor c = db.rawQuery( qry, null );
		
		return c;
	}
	
	
	@Override
	public Uri insert(Uri uri, ContentValues initialValues) {
		
		SQLiteDatabase db = mDbHelper.getWritableDatabase();
		String path = uri.getPath().substring( 1 );
		Log.println(Log.INFO, "GenericProvider", "in Insert: " + path + "\n" );

		// make sure its a uri we can understand ...
		mDbHelper.getMime( path );
		
		ContentValues values;
        if( initialValues != null ) {
            values = new ContentValues( initialValues );
        } else {
            values = new ContentValues();
        }
        
        // oh dear, we can't use the NULL column hack, sorry ...
        long rowId = db.insert( path, "", values );
        if( rowId > 0 ) {
        	Context ctx = getContext();
        	Uri tpUri = Uri.parse( "content://" + ctx.getResources().getString( R.string.authority ) + uri.getPath() );
            Uri myUri = ContentUris.withAppendedId( tpUri, rowId );
            ctx.getContentResolver().notifyChange( myUri, null );
            return myUri;
        }

        throw new SQLException("Failed to insert row into " + uri);
	}

	
	@Override
	public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
        int count = 0;
        SQLiteDatabase db = mDbHelper.getWritableDatabase();
        List<String> bits = uri.getPathSegments();
        
        switch( bits.size() ){
        case 1:
        	count = db.update( bits.get( 0 ), values, where, whereArgs );
        	break;
        	
        case 2:
            count = db.update(bits.get( 0 ), values, "_id=" + bits.get( 1 )
                    + ( !TextUtils.isEmpty( where ) ? " AND (" + where + ')' : ""), whereArgs );
            break;
            
        default:
        	throw new IllegalArgumentException( "Unknown URI " + uri );
        }
		
        getContext().getContentResolver().notifyChange( uri, null );
        return count;
	}
	
	
	@Override
	public int delete(Uri uri, String where, String[] whereArgs) {
        int count = 0;
        SQLiteDatabase db = mDbHelper.getWritableDatabase();
        List<String> bits = uri.getPathSegments();
        
        switch( bits.size() ) {
        case 1:
            count = db.delete( bits.get( 0 ), where, whereArgs );
            break;

        case 2:
            count = db.delete( bits.get( 0 ), "_id=" + bits.get( 1 )
                    + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs );
            break;

        default:
            throw new IllegalArgumentException( "Unknown URI " + uri );
        }

        getContext().getContentResolver().notifyChange( uri, null );
        return count;
	}


}
